#include "BlockQueue.hpp"
#include "Task.hpp"

int add(int x, int y)
{
    return x+y;
}


// 生产者线程：调用push接口，存入数据
void *Produce(void *args)
{
    BlockQueue<Task> *bqueue = (BlockQueue<Task> *)args;

    // 派发任务：
    while (true)
    {
        //生产前环节:获取一个任务
        int x = rand() % 100;
        usleep(1000);//主要是随机数由时间戳生成，这里延长些间隔时间
        int y = rand() % 100;
        Task assign(x, y, add);

        //生产环节：生产者生产任务到阻塞队列
        printf("%p---productor: (%d , %d )\n",pthread_self(), assign._x, assign._y);
        bqueue->Push(assign);
        sleep(2);
    }

    return nullptr;
}

// 消费者线程：调用pop接口，取出数据
void *Consume(void *args)
{
    BlockQueue<Task> *bqueue = (BlockQueue<Task> *)args;

    while (true)
    {
        //消费环节:消费者从阻塞队列中获取任务
        Task assign;
        bqueue->Pop(&assign);

        //消费后环节：处理任务
        printf("%p---consumer: addtion result is  %d + %d = %d\n", pthread_self(), assign._x, assign._y, assign());
        printf("\n");
        sleep(2);
    }

    return nullptr;
}

int main()
{
    //用于充当任务对象派发的数据资源
    srand((unsigned int)time(nullptr));

    //创建交易场所：阻塞队列
    BlockQueue<Task>* bqueue = new BlockQueue<Task>();//向阻塞队列中存入的数据是Task任务对象

    //创建两类线程：生产者、消费者
    pthread_t ptor[2], cmer[2];
    
    pthread_create(ptor, nullptr, Produce, (void*)bqueue);//arg参数：传入阻塞队列，让两个线程能够看到同一个交易场所
    pthread_create(ptor+1, nullptr, Produce, (void*)bqueue);//arg参数：传入阻塞队列，让两个线程能够看到同一个交易场所
    pthread_create(cmer, nullptr, Consume, (void*)bqueue);
    pthread_create(cmer+1, nullptr, Consume, (void*)bqueue);

    //线程终止
    pthread_join(ptor[0], nullptr);
    pthread_join(ptor[1], nullptr);
    pthread_join(cmer[0], nullptr);
    pthread_join(cmer[1], nullptr);

    delete bqueue;//注意释放空间

    return 0;
}